import os
import uuid
import json
import requests
import numpy as np
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
from pathlib import Path
from datetime import datetime
from config import Config
try:
    import tifffile
    TIFFFILE_AVAILABLE = True
except ImportError:
    TIFFFILE_AVAILABLE = False
    print("警告: tifffile库未安装，将使用PIL进行TIFF处理，可能会丢失图层信息")

class LayeredImageProcessor:
    """
    支持图层保留的图像处理器
    
    主要功能：
    1. 保留原始TIFF文件的图层信息
    2. 将JSON导入的图片放置在独立图层中
    3. 支持多种导出格式，包括保留图层的TIFF
    """
    
    def __init__(self):
        self.export_folder = Config.EXPORT_FOLDER
        self.upload_folder = Config.UPLOAD_FOLDER
        self.use_tifffile = TIFFFILE_AVAILABLE
        
    def download_image_from_url(self, url):
        """从URL下载图片"""
        try:
            response = requests.get(url, timeout=30)
            response.raise_for_status()
            return Image.open(BytesIO(response.content))
        except Exception as e:
            print(f"下载图片失败 {url}: {e}")
            return self.create_placeholder_image(300, 300, f"图片加载失败\n{url}")
    
    def create_placeholder_image(self, width, height, text="占位符"):
        """创建占位符图片"""
        # 使用不透明的红色背景，确保在TIF中可见
        img = Image.new('RGBA', (width, height), (255, 100, 100, 255))
        draw = ImageDraw.Draw(img)
        
        # 绘制明显的黑色边框
        border_width = 5
        draw.rectangle([0, 0, width-1, height-1], outline=(0, 0, 0, 255), width=border_width)
        
        try:
            font = ImageFont.truetype("arial.ttf", 16)
        except:
            try:
                font = ImageFont.truetype("simhei.ttf", 16)
            except:
                font = ImageFont.load_default()
        
        # 分行显示文本
        lines = text.split('\n')[:3]  # 最多3行
        line_height = 20
        total_height = len(lines) * line_height
        start_y = (height - total_height) // 2
        
        for i, line in enumerate(lines):
            if line.strip():
                # 截断过长的文本
                if len(line) > 20:
                    line = line[:20] + "..."
                
                bbox = draw.textbbox((0, 0), line, font=font)
                text_width = bbox[2] - bbox[0]
                x = (width - text_width) // 2
                y = start_y + i * line_height
                
                # 使用白色文字，在红色背景上显眼
                draw.text((x, y), line, fill=(255, 255, 255, 255), font=font)
        
        return img
    
    def load_tiff_layers(self, image_path):
        """
        加载TIFF文件的所有图层
        
        Returns:
            list: 图层列表，每个元素为PIL Image对象
        """
        layers = []
        
        if self.use_tifffile and Path(image_path).suffix.lower() in ['.tif', '.tiff']:
            try:
                # 使用tifffile读取多页TIFF
                with tifffile.TiffFile(image_path) as tif:
                    print(f"TIFF文件包含 {len(tif.pages)} 个页面/图层")
                    
                    for i, page in enumerate(tif.pages):
                        try:
                            # 读取每一页作为numpy数组
                            page_data = page.asarray()
                            
                            # 转换为PIL Image
                            if page_data.dtype == np.uint16:
                                # 16位图像转换为8位
                                page_data = (page_data / 256).astype(np.uint8)
                            elif page_data.dtype != np.uint8:
                                # 其他格式转换为8位
                                page_data = ((page_data - page_data.min()) / 
                                           (page_data.max() - page_data.min()) * 255).astype(np.uint8)
                            
                            # 处理不同的颜色模式
                            if len(page_data.shape) == 2:
                                # 灰度图像
                                layer_image = Image.fromarray(page_data, mode='L')
                                layer_image = layer_image.convert('RGBA')
                            elif len(page_data.shape) == 3:
                                if page_data.shape[2] == 3:
                                    # RGB图像
                                    layer_image = Image.fromarray(page_data, mode='RGB')
                                    layer_image = layer_image.convert('RGBA')
                                elif page_data.shape[2] == 4:
                                    # RGBA图像
                                    layer_image = Image.fromarray(page_data, mode='RGBA')
                                else:
                                    # 其他多通道图像，取前3个通道
                                    layer_image = Image.fromarray(page_data[:,:,:3], mode='RGB')
                                    layer_image = layer_image.convert('RGBA')
                            else:
                                print(f"警告: 第{i}页的数据格式不支持: {page_data.shape}")
                                continue
                            
                            layers.append(layer_image)
                            print(f"成功加载第{i+1}层，尺寸: {layer_image.size}")
                            
                        except Exception as e:
                            print(f"加载第{i}页失败: {e}")
                            continue
                            
            except Exception as e:
                print(f"使用tifffile加载TIFF失败: {e}")
                # 回退到PIL方法
                return self._load_tiff_with_pil(image_path)
        else:
            # 使用PIL加载（只能获取第一层）
            return self._load_tiff_with_pil(image_path)
        
        return layers
    
    def _load_tiff_with_pil(self, image_path):
        """使用PIL加载TIFF文件（回退方法）"""
        layers = []
        try:
            with Image.open(image_path) as img:
                if img.mode != 'RGBA':
                    img = img.convert('RGBA')
                layers.append(img.copy())
                print(f"使用PIL加载TIFF，只能获取第一层，尺寸: {img.size}")
        except Exception as e:
            print(f"PIL加载TIFF失败: {e}")
        
        return layers
    
    def create_layered_image(self, template, regions, customization_data, export_format='png'):
        """
        创建保留图层信息的定制图片
        
        Args:
            template: 底板模板信息
            regions: 区域信息
            customization_data: 定制数据
            export_format: 导出格式 ('png', 'tif', 'jpg')
            
        Returns:
            Path: 导出文件路径
        """
        canvas_width = template['width']
        canvas_height = template['height']
        
        # 存储所有图层
        layers = []
        layer_names = []
        
        # 1. 加载底板图层
        if template.get('image_path'):
            try:
                image_path = template['image_path']
                
                if Path(image_path).is_absolute():
                    template_image_path = Path(image_path)
                else:
                    template_image_path = self.upload_folder / image_path
                
                if template_image_path.exists():
                    print(f"加载底板图片: {template_image_path}")
                    base_layers = self.load_tiff_layers(str(template_image_path))
                    
                    # 检查底板图层尺寸是否与模板匹配
                    if base_layers and base_layers[0].size != (canvas_width, canvas_height):
                        print(f"警告：底板图层尺寸({base_layers[0].size})与模板尺寸({canvas_width}x{canvas_height})不匹配")
                        print(f"使用底板原始尺寸: {base_layers[0].size}")
                        # 更新画布尺寸为底板实际尺寸
                        canvas_width, canvas_height = base_layers[0].size
                    
                    for i, layer in enumerate(base_layers):
                        # 直接使用原始图层，不进行任何缩放或居中操作
                        layers.append(layer)
                        layer_names.append(f"原始图层_{i+1}")
                        print(f"保留原始图层 {i+1}: {layer.size}")
                else:
                    print(f"底板图片文件不存在: {template_image_path}")
                    # 创建空白底板
                    empty_base = Image.new('RGBA', (canvas_width, canvas_height), (255, 255, 255, 255))
                    layers.append(empty_base)
                    layer_names.append("空白底板")
            except Exception as e:
                print(f"加载底板图片失败: {e}")
                # 创建空白底板
                empty_base = Image.new('RGBA', (canvas_width, canvas_height), (255, 255, 255, 255))
                layers.append(empty_base)
                layer_names.append("空白底板")
        else:
            # 创建空白底板
            empty_base = Image.new('RGBA', (canvas_width, canvas_height), (255, 255, 255, 255))
            layers.append(empty_base)
            layer_names.append("空白底板")
        
        # 2. 处理JSON导入的图片，每个图片创建独立图层
        processed_count = 0
        
        for region_index, region_data in customization_data.get('regions', {}).items():
            elements = region_data.get('elements', [])
            print(f"处理区域 {region_index}，包含 {len(elements)} 个元素")
            
            for element_idx, element in enumerate(elements):
                try:
                    # 为每个元素创建独立图层
                    element_layer = self._create_element_layer(
                        element, canvas_width, canvas_height
                    )
                    
                    if element_layer:
                        layers.append(element_layer)
                        layer_name = f"JSON图片_{region_index}_{element_idx+1}"
                        layer_names.append(layer_name)
                        processed_count += 1
                        print(f"添加JSON图层: {layer_name}")
                    else:
                        print(f"跳过无效元素: {element.get('image_url', 'No URL')}")
                        
                except Exception as e:
                    print(f"处理元素失败: {e}")
                    continue
        
        original_layers = len(layers) - processed_count
        print(f"原始图层: {original_layers}, JSON图层: {processed_count}, 总图层: {len(layers)}")
        
        # 3. 生成文件名
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        unique_id = str(uuid.uuid4())[:8]
        
        # 4. 根据导出格式保存文件
        if export_format.lower() in ['tif', 'tiff']:
            return self._save_layered_tiff(layers, layer_names, timestamp, unique_id)
        else:
            # 对于非TIFF格式，合并所有图层
            return self._save_flattened_image(layers, export_format, timestamp, unique_id)
    
    def _create_element_layer(self, element, canvas_width, canvas_height):
        """为单个元素创建图层"""
        image_url = element.get('image_url')
        if not image_url:
            return None
        
        
        # 下载图片
        element_image = self.download_image_from_url(image_url)
        if not element_image:
            return None
        
        
        # 转换为RGBA模式
        if element_image.mode != 'RGBA':
            element_image = element_image.convert('RGBA')
        
        # 创建图层画布（使用实际画布尺寸）
        layer = Image.new('RGBA', (canvas_width, canvas_height), (0, 0, 0, 0))  # 完全透明背景
        
        # 获取用户放置数据
        user_placement_data = element.get('user_placement_data', {})
        
        # 应用变换
        element_image = self._apply_transformations(element_image, user_placement_data)
        
        # 获取放置位置
        position = user_placement_data.get('position', {})
        x = int(position.get('x', 0))
        y = int(position.get('y', 0))
        
        # 确保不超出边界
        x = max(0, min(x, canvas_width - element_image.width))
        y = max(0, min(y, canvas_height - element_image.height))
        
        # 粘贴到图层
        try:
            layer.paste(element_image, (x, y), element_image)
            return layer
        except Exception as e:
            print(f"粘贴图片失败: {e}")
            return None
    
    def _apply_transformations(self, image, user_placement_data):
        """应用变换操作"""
        # 获取缩放信息
        scale = user_placement_data.get('scale', {})
        scale_x = scale.get('scale_x', 1.0)
        scale_y = scale.get('scale_y', 1.0)
        
        # 获取目标尺寸
        dimension = user_placement_data.get('dimension', {})
        target_width = dimension.get('width')
        target_height = dimension.get('height')
        
        # 应用尺寸调整
        if target_width and target_height:
            image = image.resize((int(target_width), int(target_height)), Image.Resampling.LANCZOS)
        elif scale_x != 1.0 or scale_y != 1.0:
            new_width = int(image.width * scale_x)
            new_height = int(image.height * scale_y)
            image = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
        
        # 应用旋转
        angle = user_placement_data.get('angle_of_rotation', 0)
        if angle != 0:
            image = image.rotate(angle, expand=True, fillcolor=(255, 255, 255, 0))
        
        return image
    
    def _save_layered_tiff(self, layers, layer_names, timestamp, unique_id):
        """保存为多图层TIFF文件"""
        filename = f"layered_{timestamp}_{unique_id}.tif"
        export_path = self.export_folder / filename
        
        # 优先使用PIL的方法保存，确保与PS兼容
        return self._save_layered_tiff_with_pil(layers, export_path, layer_names)
    
    def _save_layered_tiff_with_pil(self, layers, export_path, layer_names=None):
        """使用PIL保存TIFF，尝试保留图层"""
        try:
            if len(layers) == 1:
                # 单图层
                base = layers[0]
                if base.mode != 'RGBA':
                    base = base.convert('RGBA')
                base.save(export_path, 'TIFF', compression='lzw')
                print(f"保存单图层TIFF: {export_path}")
            else:
                # 多图层 - 使用PIL的append_images参数
                base = layers[0]
                if base.mode != 'RGBA':
                    base = base.convert('RGBA')
                
                additional_layers = []
                for layer in layers[1:]:
                    if layer.mode != 'RGBA':
                        layer = layer.convert('RGBA')
                    additional_layers.append(layer)
                
                # 使用save_all和append_images保存多图层
                base.save(
                    export_path, 
                    'TIFF', 
                    compression='lzw',
                    save_all=True,
                    append_images=additional_layers
                )
                
                print(f"保存多图层TIFF: {export_path}, 图层数: {len(layers)}")
            
        except Exception as e:
            print(f"PIL保存TIFF失败: {e}")
            # 如果多图层保存失败，尝试合并保存
            try:
                base = layers[0].copy()
                for layer in layers[1:]:
                    base = Image.alpha_composite(base, layer)
                base.save(export_path, 'TIFF', compression='lzw')
                print(f"备用方案：保存合并TIFF: {export_path}")
            except Exception as e2:
                print(f"合并保存也失败: {e2}")
                raise
        
        return export_path
    
    def _save_flattened_image(self, layers, export_format, timestamp, unique_id):
        """保存为合并的图像文件"""
        # 合并所有图层
        if len(layers) > 1:
            base = layers[0].copy()
            for layer in layers[1:]:
                base = Image.alpha_composite(base, layer)
        else:
            base = layers[0]
        
        # 根据格式设置参数
        if export_format.lower() in ['jpg', 'jpeg']:
            filename = f"flattened_{timestamp}_{unique_id}.jpg"
            save_format = 'JPEG'
            save_kwargs = {'quality': 95}
            # JPEG不支持透明度
            if base.mode == 'RGBA':
                rgb_base = Image.new('RGB', base.size, (255, 255, 255))
                rgb_base.paste(base, mask=base.split()[-1])
                base = rgb_base
        else:  # PNG
            filename = f"flattened_{timestamp}_{unique_id}.png"
            save_format = 'PNG'
            save_kwargs = {'optimize': True}
        
        export_path = self.export_folder / filename
        base.save(export_path, save_format, **save_kwargs)
        
        print(f"保存合并图像: {export_path} (格式: {save_format})")
        return export_path
